import { ElementPropertyConfig } from '@farris/ide-property-panel';
import { FarrisDesignBaseComponent } from '@farris/designer-element';
import { GridFieldSchema } from '../../../schema/datagrid';
import { GridFieldProp } from '../property/property-config';
import { NoCodeGridFieldProp } from '../property/nocode-property-config';
import { FormPropertyChangeObject } from '../../../../../../entity/property-change-entity';
import { DesignViewModelService, DesignerEnvType, DomService, FormSchemaEntityField$Type, FormBasicService, DgControl } from '@farris/designer-services';
import FdInputGroupComponent from '../../../../../../components/input/input-group/component/fd-input-group';


export default class FdDataGridFieldComponent extends FarrisDesignBaseComponent {
    envType: DesignerEnvType;
    /** 单列所属的父级DataGrid实例 */
    public parentGridInstance: FarrisDesignBaseComponent;

    public focusedFieldId: string;

    /** 列的绑定信息是否有效 */
    isValidBinding = true;

    constructor(component: any, options: any, parentGridInstance: FarrisDesignBaseComponent) {
        super(component, options);
        this.parentGridInstance = parentGridInstance;

        this.viewModelId = this.parentGridInstance.viewModelId;
        this.componentId = this.parentGridInstance.componentId;

        const serviceHost = this.options.designerHost;
        const formBasicService = serviceHost.getService('FormBasicService') as FormBasicService;
        if (formBasicService) {
            this.envType = formBasicService.envType;
        }

        this.adaptOldControlSchema();
    }
    getDefaultSchema(): any {
        return GridFieldSchema;
    }

    render(): any {
        this.init();
        this.checkBindingFormFieldValidation();

        return this.renderTemplate('GridField', {
            component: this.component,
            focusedFieldId: this.focusedFieldId,
            className: this.getSelectedClassName(),
            isValidBinding: this.isValidBinding
        });
    }

    attach(element: HTMLElement): Promise<any> {
        this.element = element;
        const superAttach = super.attach(element);

        this.addGridFieldClickEvent();

        return superAttach;
    }
    /**
     * 设置列、列编辑器的展示名称和路径，用于交互面板已绑定事件窗口
     */
    setComponentBasicInfoMap() {
        const domService = this.options.designerHost.getService('DomService') as DomService;

        let parentPath = '表格';

        // 先取父级表格上的路径信息
        const dataGridBasicInfo = domService.controlBasicInfoMap.get(this.parentGridInstance.id);
        if (dataGridBasicInfo && dataGridBasicInfo.parentPathName) {
            parentPath = dataGridBasicInfo.parentPathName;
        }

        // 列的展示名称和路径
        domService.controlBasicInfoMap.set(this.component.id, {
            showName: this.component.caption,
            parentPathName: `${parentPath} > ${this.component.caption}`
        });

        // 列编辑器的展示名称及路径
        if (this.component.editor) {
            domService.controlBasicInfoMap.set(this.component.editor.id, {
                showName: this.component.caption,
                parentPathName: `${parentPath} > ${this.component.caption}`
            });

            // 智能输入框内部嵌套的弹窗按钮路径信息
            if (this.component.editor.type === DgControl.InputGroup.type) {
                const inputGroupControl = new FdInputGroupComponent(this.component.editor, this.options);
                inputGroupControl.setComponentExtendInfoMap();
            }
        }


    }
    /**
     * 增加单列的点击事件，用于触发属性面板
     */
    private addGridFieldClickEvent() {
        this.addEventListener(this.element, 'click', (event) => {
            event.stopPropagation();
            event.preventDefault();

            // 选中当前列
            this.focusGridField();

            // 手动触发点击组件事件  展示属性面板
            if (this.parentGridInstance) {
                this.parentGridInstance.emit('componentClicked', { componentInstance: this });
            }
        });
    }


    /**
     * 选中单列状态
     * @param itemElement 按钮元素
     */
    private focusGridField() {
        const currentSelectedElements = document.getElementsByClassName('dgComponentSelected');
        for (const ele of Array.from(currentSelectedElements)) {
            ele.classList.remove('dgComponentSelected');
        }
        this.element.classList.add('dgComponentSelected');

        this.focusedFieldId = this.component.id;
    }


    /**
     * 组装属性面板配置数据
     */
    getPropertyConfig(): ElementPropertyConfig[] {
        const serviceHost = this.options && this.options.designerHost;

        if (this.envType === DesignerEnvType.noCode) {
            const prop: NoCodeGridFieldProp = new NoCodeGridFieldProp(serviceHost, this.viewModelId, this.componentId);
            const propertyConfig: ElementPropertyConfig[] = prop.getPropConfig(this.component, this.parentGridInstance.component);
            return propertyConfig;
        } else {
            const prop: GridFieldProp = new GridFieldProp(serviceHost, this.viewModelId, this.componentId);
            const propertyConfig: ElementPropertyConfig[] = prop.getPropConfig(this.component, this.parentGridInstance.component);
            return propertyConfig;
        }
    }


    /**
     * 属性变更后事件：默认监听样式类属性变更，并触发模板重绘
     * @param changeObject 变更集
     * @param propertyIDs 需要额外监听的属性ID列表
     */
    onPropertyChanged(changeObject: FormPropertyChangeObject): void {
        const dynamicPropertyIDs = ['caption', 'editor.require'];

        const propertyPath = changeObject.propertyPath ? changeObject.propertyPath + '.' : '';
        if (dynamicPropertyIDs.includes(propertyPath + changeObject.propertyID)) {
            this.redraw();
        }

        // 列编辑器内切换控件类型后，需要重新组装属性面板配置数据
        if (propertyPath + changeObject.propertyID === 'editor.type' && this.parentGridInstance) {
            this.parentGridInstance.emit('componentClicked', { componentInstance: this, needUpdatePropertyPanel: true });
            return;
        }

        //  切换绑定后，列编辑器分类下的属性需要重构
        if (changeObject.propertyID === 'binding' && this.component.editor && this.parentGridInstance) {
            this.parentGridInstance.emit('componentClicked', { componentInstance: this, needUpdatePropertyPanel: true });
            return;
        }

        // 绑定无效字段的列，切换绑定后，需要重绘，并重新组装属性面板配置数据
        if (!this.isValidBinding && changeObject.propertyID === 'binding' && this.parentGridInstance) {
            this.redraw();
            this.parentGridInstance.emit('componentClicked', { componentInstance: this, needUpdatePropertyPanel: true });
            return;
        }
        // 修改列宽度后，需要触发整个datagrid的重绘
        if (propertyPath + changeObject.propertyID === 'size.width' && this.parentGridInstance) {
            this.parentGridInstance.redraw();
            return;
        }
    }

    /**
     * 获取当前列的选中样式，用于在redraw时，保持选中样式
     */
    getSelectedClassName() {
        let className = '';

        // 用于重新渲染组件时，保持选中样式
        if (this.element && this.element.className && this.element.className.includes('dgComponentSelected')) {
            className += 'dgComponentSelected';
        }
        return className;
    }

    private adaptOldControlSchema() {

        if (['date', 'string'].includes(this.component.dataType) && !this.component.hasOwnProperty('localizationType')) {
            this.component.localizationType = 'Date';
        }
        if ('datetime' === this.component.dataType && !this.component.hasOwnProperty('localizationType')) {
            this.component.localizationType = 'DateTime';
        }

        // 列编辑器内部的title要与外部一致
        if (this.component.editor && this.component.editor.title !== this.component.caption) {
            this.component.editor.title = this.component.caption;
        }
    }

    checkBindingFormFieldValidation() {
        this.isValidBinding = true;
        const dgVMService = this.options.designerHost.getService('DesignViewModelService') as DesignViewModelService;
        const dgViewModel = dgVMService.getDgViewModel(this.viewModelId);
        const dgVMField = dgViewModel.fields.find(f => f.id === this.component.binding.field);

        // schema中已移除的字段
        if (!dgVMField) {
            this.isValidBinding = false;
        }
        // 在schema中类型已发生变更的字段，例如由普通文本字段改成了关联字段
        if (dgVMField.$type !== FormSchemaEntityField$Type.SimpleField) {
            this.isValidBinding = false;
        }

    }
}
